Skip to content

fix(SampleApp): start new conversations the way the UI cookbook does - #3953

Merged
isekovanic merged 2 commits into
developfrom
fix/sample-app-start-conversation
Nov 9, 2026
Merged

isekovanic merged 2 commits into
developfrom
fix/sample-app-start-conversation

Conversation

@isekovanic

@isekovanic isekovanic commented Nov 9, 2026 •

Copy link
Copy Markdown
Contributor

Ticket: https://linear.app/stream/issue/REACT-1537

🎯 Goal

Make the SampleApp start new conversations the way the v10 "Starting a conversation" UI cookbook does, so the sample exercises the path integrators follow.

It also bumps stream-chat to 10.0.1, which has the fix for the first-message error (GetStream/stream-chat-js#2007).

Commit Change
39a2be3b0 SampleApp new-conversation screen follows the UI cookbook
caec3a002 stream-chat bumped to 10.0.1

Its new-conversation screen had a custom send button that composed the message, called channel.watch() and the raw channel.sendMessage(), then replaced the screen with ChannelScreen. The message never showed as sending, and the cookbook's flow was never run in the sample, which is how the first-message error fixed in GetStream/stream-chat-js#2007 went unnoticed.

🛠 Implementation details

  • utils/startConversation.ts holds the cookbook's two helpers. startLocalConversation() gets the channel from its members and places an empty first page while it's provisional, so the list shows its empty state. createOnFirstSend() is a sendMessageRequest handler: for a provisional channel it calls Channel.watch(), which creates the channel, and sends on the instance watch() resolves with. Every other channel sends through the default request.
  • useChatClient registers the handler in its existing client.config.set() call, where the client is created.
  • NewDirectMessagingScreen builds its draft with startLocalConversation(), uses the default MessageComposer, and passes overrideOwnCapabilities (sendMessage and sendLinks) only while the channel is provisional. It stays open after the first send, and <Channel> moves to the created channel, or to the one that superseded it.
  • Once the first message creates a conversation started on this screen, NewConversationHeader replaces the recipient picker with the channel header. An existing conversation keeps the picker, so its recipients can still be changed.
  • ChannelHeader is exported from ChannelScreen with two optional props: onBack, so the new-conversation screen still resets its user search on back, and inSafeArea, since that screen already applies the top inset. ChannelScreen passes neither and is unchanged.
  • NewDirectMessagingSendButton is removed.

The other example apps don't start conversations from members (ExpoChatGPTSample creates its channels with an id), so they need no change.

stream-chat goes from ^10.0.0 to ^10.0.1 in the SDK and every example app, as in #3951. 10.0.1 is 10.0.0 plus GetStream/stream-chat-js#2007: the first message in a channel whose newest page was loaded empty now starts the newest interval, so jumpToTheLatestMessage() no longer fails right after the first send of a new conversation.

🎨 UI Changes

The new-conversation screen keeps the conversation open after the first message and swaps the recipient picker for the channel header. Before, it navigated to ChannelScreen.

🧪 Testing

Tested in SampleApp on iOS (debug build, iPhone 17 Pro simulator), starting new conversations with throwaway users. Each first send went through the superseded-channel path from the cookbook report.

  • With stream-chat 10.0.0-rc.34, a new direct conversation sends from the same screen, and stream-chat emits api:message:jumpToLatest:failed, the error the cookbook report describes.
  • With a local build of fix: start the newest interval with the first message in a channel loaded empty stream-chat-js#2007 (the code 10.0.1 ships), the same flow emits no notifications and the channel the screen moves to is at the newest messages.
  • A new group of three: the empty state shows before the first message and the attach button is hidden while the channel is provisional. After the send, the channel header replaces the picker ("3 members, 1 online"), back returns to the channel list, and "New Chat" opens empty again. The created channels show in the channel list, and ChannelScreen's header is unchanged.
  • On 10.0.1: the full unit suite, yarn test:typecheck, SampleApp tsc and yarn lint pass.

☑️ Checklist

  • I have signed the Stream CLA (required)
  • PR targets the develop branch
  • Documentation is updated
  • New code is tested in main example apps, including all possible scenarios
    • SampleApp iOS and Android
    • Expo iOS and Android

The new-conversation screen now creates its channel in a
`sendMessageRequest` handler on the first send, as the "Starting a
conversation" UI cookbook does, instead of a custom send button that
called the raw API and replaced the screen. The screen stays open after
the first send, and the channel header replaces the recipient picker once
the conversation exists.
@Stream-SDK-Bot

Copy link
Copy Markdown
Contributor

SDK Size

title develop branch diff status
js_bundle_size 2026 KB 2026 KB 0 B 🟢
ai_components_size 163 KB 163 KB 0 B 🟢

@isekovanic
isekovanic merged commit e6ad005 into develop Nov 9, 2026
12 of 13 checks passed
@isekovanic
isekovanic deleted the fix/sample-app-start-conversation branch November 9, 2026 13:58
isekovanic added a commit that referenced this pull request Nov 9, 2026
…expo-av is installed (#3954)

Ticket: https://linear.app/stream/issue/REACT-1538

Stacked on #3953.

## 🎯 Goal

Stop `stream-chat-expo` from logging "install the expo-av package" in
apps that have `expo-audio` installed. Audio works in those apps, so the
log is wrong, and it points to a package Expo has deprecated.

## 🛠 Implementation details

`AudioVideo.ts` logged whenever `require('expo-av')` failed, without
checking for `expo-audio`. `Audio.ts` and `Sound.ts` use `expo-audio`
first and fall back to `expo-av` only when it's missing.

- The log is removed from `AudioVideo.ts`.
- `Sound.ts` already loads both packages, so it now logs once, only when
neither is installed, and names `expo-audio`, for playback and voice
recording.

The `expo-av` fallback stays. `stream-chat-expo` v10 supports Expo 53
and 54, where `expo-av` still works, so an app that never moved to
`expo-audio` keeps its audio without a log. The same log has been on
`develop` since v7, so this isn't a v10 regression.

## 🎨 UI Changes

None.

## 🧪 Testing

- New `Sound.test.ts`, with the optional packages mocked. With only
`expo-audio` installed there's no log, with only `expo-av` there's no
log, and with neither there's one log naming `expo-audio`. Without the
fix, the first and third cases fail.
- The expo-package typecheck, `yarn test:typecheck`, `prettier` and
`yarn lint` pass.

## ☑️ Checklist

- [x] I have signed the [Stream
CLA](https://docs.google.com/forms/d/e/1FAIpQLScFKsKkAJI7mhCr7K9rEIOpqIDThrWxuvxnwUq2XkHyG154vQ/viewform)
(required)
- [ ] PR targets the `develop` branch
- [ ] Documentation is updated
- [ ] New code is tested in main example apps, including all possible
scenarios
  - [ ] SampleApp iOS and Android
  - [ ] Expo iOS and Android
This was referenced Nov 10, 2026
@stream-ci-bot

Copy link
Copy Markdown
Contributor

🎉 This PR is included in version 10.0.1 🎉

The release is available on:

Your semantic-release bot 📦🚀

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants